﻿#include "loghandler.h"
#include <QDateTime>
#include <QThread>
#include <QDebug> // 用于在控制台也输出一份
#include <QFileInfo>
#include <QDir>
#include <QCoreApplication>
#include <QStandardPaths>

// 初始化静态成员
QFile *LogHandler::m_logFile = nullptr;
QTextStream *LogHandler::m_logStream = nullptr;
QTextStream *LogHandler::m_consoleStream = nullptr;

QMutex LogHandler::m_mutex;
LogHandler *LogHandler::m_instance = nullptr;

LogHandler::LogHandler(QObject *parent)
    : QObject(parent)
{
    QString logPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/logs";
    if (!QDir().mkpath(logPath)) {
        qWarning() << "无法创建日志目录：" << logPath;
        return;
    }

    QString logFileName = QDir(logPath).filePath(QString("%1.log").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd")));
    m_logFile = new QFile(logFileName);
    if (m_logFile->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
        m_logStream = new QTextStream(m_logFile);
        m_consoleStream = new QTextStream(stderr);
        m_logStream->setCodec("UTF-8");
        qDebug() << "日志文件已打开：" << logFileName;
    } else {
        qWarning() << "无法打开日志文件：" << logFileName << "错误：" << m_logFile->errorString();
    }
}

LogHandler::~LogHandler()
{
    if (m_logStream) {
        delete m_logStream;
        m_logStream = nullptr;
    }
    if (m_logFile) {
        if (m_logFile->isOpen()) {
            m_logFile->close();
        }
        delete m_logFile;
        m_logFile = nullptr;
    }
    if (m_consoleStream) {
        delete m_consoleStream;
        m_consoleStream = nullptr;
    }
}

LogHandler *LogHandler::instance()
{
    if (!m_instance) {
        // 使用互斥锁保证线程安全
        QMutexLocker locker(&m_mutex);
        if (!m_instance) {
            m_instance = new LogHandler();
        }
    }
    return m_instance;
}

void LogHandler::install()
{
    instance(); // 确保单例已创建
    qInstallMessageHandler(messageHandler);
}

// 核心：自定义消息处理函数
void LogHandler::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    // 加锁，防止多线程同时写入日志造成混乱
    QMutexLocker locker(&m_mutex);

    QString level;
    switch (type) {
    case QtDebugMsg:
        level = "DEBUG";
        break;
    case QtInfoMsg:
        level = "INFO";
        break;
    case QtWarningMsg:
        level = "WARN";
        break;
    case QtCriticalMsg:
        level = "CRITICAL";
        break;
    case QtFatalMsg:
        level = "FATAL";
        break;
    }

    // 获取当前时间
    QString currentTime = QDateTime::currentDateTime().toString("MMdd hh:mm:ss.zzz");

#ifdef QT_DEBUG
    // 获取文件名、行号、函数名
    QString fileName = context.file ? QFileInfo(context.file).fileName() : "unknown";
    fileName = fileName.section('.', 0, 0);
    int line = context.line;
    QString functionName = context.function ? context.function : "unknown";
    QString functionSignature = functionName.section('(', 0, 0);
    QString pureFunctionName = functionSignature.section(':', -1, -1).trimmed();

    // 格式: [时间] [线程ID] [日志等级] [文件名:行号,函数名] 日志内容
    QString formattedMessage = QString("[%1] [TID:%2] [%3] [%4:%5,%6] %7").arg(currentTime).arg(quintptr(QThread::currentThreadId())).arg(level).arg(fileName).arg(line).arg(pureFunctionName).arg(msg);
#else
    QString formattedMessage = QString("[%1] [TID:%2] [%3] %4").arg(currentTime).arg(quintptr(QThread::currentThreadId())).arg(level).arg(msg);
#endif

    // 将格式化后的消息写入文件
    if (m_logStream) {
        (*m_logStream) << formattedMessage << endl;
        m_logStream->flush(); // 实时刷新到文件，防止程序崩溃时日志丢失
    }
    // 写入控制台
    if (m_consoleStream) {
        (*m_consoleStream) << formattedMessage << endl;
    }

    // 如果是致命错误，则终止程序
    if (type == QtFatalMsg) {
        abort();
    }
}
